﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Timers;
using Reborn_WorldServer;
using Reborn_WorldServer.App1AppHandler.Spells.Interfaces;

namespace Reborn_Server.App1AppHandler
{
    public class Spell_FireArrow : Buff, IInstantCast
    {
        //lvl 3
        private int Rank1InstantLow = 135;
        private int Rank1InstantHigh = 185;
        // 20 * 8 = 160 base
        private int Rank1BaseDotDamage = 20;

        //lvl 15
        private int Rank2InstantLow = 200;
        private int Rank2InstantHigh = 250;
        // 30 * 8 = 240 base
        private int Rank2BaseDotDamage = 30;

        //lvl 25
        private int Rank3InstantLow = 330;
        private int Rank3InstantHigh = 380;
        // 45 * 8 = 360 base
        private int Rank3BaseDotDamage = 45;


        private int CalcDotDamage = 3;

        public int BaseDotDamage
        {
            get 
            {
                if (spellIcon.Name.IndexOf("Rank 2") > -1)
                    return Rank2BaseDotDamage;
                else if (spellIcon.Name.IndexOf("Rank 3") > -1)
                    return Rank3BaseDotDamage;

                return Rank1BaseDotDamage;
            }
        }
        public int InstantHigh
        {
            get
            {
                if (spellIcon.Name.IndexOf("Rank 2") > -1)
                    return Rank2InstantHigh;
                else if (spellIcon.Name.IndexOf("Rank 3") > -1)
                    return Rank3InstantHigh;

                return Rank1InstantHigh;
            }
        }
        public int InstantLow
        {
            get
            {
                if (spellIcon.Name.IndexOf("Rank 2") > -1)
                    return Rank2InstantLow;
                else if (spellIcon.Name.IndexOf("Rank 3") > -1)
                    return Rank3InstantLow;

                return Rank1InstantLow;
            }
        }


        public Spell_FireArrow() 
        {
            spellTimer.Interval = 2000;
            minutesLeft = -2;
            ticksLeft = 8;
        }

        override public void Resume(CreatureBase targetCreatureBase, SpellIcon _spellIcon, int timeRemaining, int castLevel, int castCharacterID, int castInt, int castWis, int optionalValue, string xmlData)
        {
            minutesLeft = -2;

            base.Resume(targetCreatureBase, _spellIcon, timeRemaining, castLevel, castCharacterID, castInt, castWis, optionalValue, xmlData);

            int DotAmount = BaseDotDamage * ticksLeft;
            DotAmount = SkillManager.AdjustForCombat(castLevel, DotAmount, castInt);
            DotAmount = TargetCreatureBase.CalculateGetSpellDamagePerResists(DotAmount, base.spellIcon.Skill);
            CalcDotDamage = DotAmount / ticksLeft;

            ticksLeft = timeRemaining;

            spellTimer.Start();
        }

        private void MainCast(CreatureBase castingCreatureBase)
        {
            List<Character> CharactersWithin12 = new List<Character>();
            MapItem CurrentMapItem = null;
            foreach (MapItem mapitem in TargetCreatureBase.currentMapItem.mapItemsWithin12)
            {
                foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                {
                    if (creaturebase is Character)
                        CharactersWithin12.Add((Character)creaturebase);
                }

                if (mapitem.MapX == TargetCreatureBase.MapX && mapitem.MapY == TargetCreatureBase.MapY)
                    CurrentMapItem = mapitem;
            }

            int DotAmount = BaseDotDamage * ticksLeft;
            DotAmount = SkillManager.AdjustForCombat(CastingCreatureLevel, DotAmount, CastingCreatureInt);
            DotAmount = TargetCreatureBase.CalculateGetSpellDamagePerResists(DotAmount, base.spellIcon.Skill);
            CalcDotDamage = DotAmount / ticksLeft;

            int DamageAmount = Managers.GameHandler.random.Next(InstantLow, InstantHigh + 1);
            DamageAmount = SkillManager.AdjustForCombat(CastingCreatureLevel, DamageAmount, CastingCreatureInt);
            int actualDamage = TargetCreatureBase.CalculateGetSpellDamagePerResists(DamageAmount, base.spellIcon.Skill);
            int absorbedDamage;
            TargetCreatureBase.InflictSpellDamage(actualDamage,
                castingCreatureBase is Character ? castingCreatureBase.ID : -1,
                castingCreatureBase is Creature ? castingCreatureBase.CreatureID : -1,
                spellIcon.Skill, out absorbedDamage);

            TargetCreatureBase.Update_Character();

            actualDamage = actualDamage - absorbedDamage;

            if (castingCreatureBase is Character && castingCreatureBase != TargetCreatureBase)
            {
                Character character = (Character)castingCreatureBase;
                Message msg = new Message();
                msg.Text = "You burn " + TargetCreatureBase.Name + "! (" + actualDamage.ToString() + ")";
                if (absorbedDamage != 0)
                    msg.Text = msg.Text + " ABSORBED " + absorbedDamage.ToString();

                msg.CreatureID = character.CreatureID;
                msg.Type = "spelloffense";
                character.AddMessage(msg);
            }
            if (TargetCreatureBase is Character)
            {
                Character character = (Character)TargetCreatureBase;
                Message msg = new Message();
                msg.Text = "You have been burned by " + castingCreatureBase.Name + "! (" + actualDamage.ToString() + ")";
                if (absorbedDamage != 0)
                    msg.Text = msg.Text + " ABSORBED " + absorbedDamage.ToString();

                msg.CreatureID = character.CreatureID;
                msg.Type = "damaged";
                character.AddMessage(msg);
            }


            if (TargetCreatureBase.HP < 1)
            {
                if (!(TargetCreatureBase is Character))
                    CurrentMapItem.CreaturesBases.Remove(TargetCreatureBase);

            }
            foreach (Character character in CharactersWithin12)
            {
                if (Math.Abs(character.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(character.MapY - TargetCreatureBase.MapY) <= 4)
                {
                    if (TargetCreatureBase.HP < 1)
                        character.AddMapItem(CurrentMapItem);
                    else
                        character.UpdateCreatureBaseHp(TargetCreatureBase);
                }
                character.PlaySound("FireBolt", castingCreatureBase.MapX, castingCreatureBase.MapY);
            }

            castingCreatureBase.Update_Character();
            TargetCreatureBase.buffManager.UpdateBuffs();

            //Only start the spell timer if the creature is alive (if the direct damage killed it,
            //the timer will already be disposed and the buff removed)
            if (TargetCreatureBase.HP > 0)
                spellTimer.Start();
        }

        public void Cast(CreatureBase myCreatureBase, int CastLevel, long CreatureGUID)
        {
            List<MapItem> MapItemsWithin12;
            if (base.InitializeCast(myCreatureBase, CastLevel, CreatureGUID, false, out MapItemsWithin12) == false)
                return;

            MainCast(myCreatureBase);
        }
        protected override void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            LockItem lockitem = TargetCreatureBase.GameHandler.GetLockItem(TargetCreatureBase.MapID, TargetCreatureBase.Instance);

            lock (lockitem.LockObj)
            {
                //This buff has been removed, do nothing (this can occur if the buff gets overwritten exactly when this timer fires)
                if (TargetCreatureBase.buffManager.hasBuff(this.SpellID) == false)
                    return;

                if (TargetCreatureBase.HP < 1)
                {
                    RemoveSpell(true, false);
                    return;
                }

                //Map CurrentMap = TargetCreatureBase.GameHandler.GetMap(TargetCreatureBase.MapID, TargetCreatureBase.Instance);
                //List<MapItem> MapItemsWithin8 = new List<MapItem>();
                List<Character> CharactersWithin8 = new List<Character>();
                MapItem CurrentMapItem = TargetCreatureBase.currentMapItem;
                foreach (MapItem mapitem in TargetCreatureBase.currentMapItem.mapItemsWithin8)
                {
                    foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                    {
                        if (creaturebase is Character)
                            CharactersWithin8.Add((Character)creaturebase);
                    }
                 }
                int absorbedDamage;
                TargetCreatureBase.InflictSpellDamage(CalcDotDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);

                int actualDamage = CalcDotDamage - absorbedDamage;

                string messageText = "You are burning (" + actualDamage.ToString() + ")";
                if (absorbedDamage != 0)
                    messageText = messageText + " ABSORBED " + absorbedDamage.ToString();
                TargetCreatureBase.SendMessage(messageText, "spelldamaged");

                if (!(TargetCreatureBase is Character) || TargetCreatureBase.ID != CastingCharacterID)
                {
                    messageText = "You burn " + TargetCreatureBase.Name + " (" + actualDamage.ToString() + ")";
                    if (absorbedDamage != 0)
                        messageText = messageText + " ABSORBED " + absorbedDamage.ToString();
                    Managers.GameHandler.TrySendMessage(CastingCharacterID, messageText, "spelldamage");
                }

                TargetCreatureBase.Update_Character();

                if (TargetCreatureBase.HP < 1)
                {
                    TargetCreatureBase.SendMessage("You have been slain!", "slain");
                    Managers.GameHandler.TrySendMessage(CastingCharacterID, "You have slain " + TargetCreatureBase.Name + "!", "slay");

                    if (!(TargetCreatureBase is Character))
                        CurrentMapItem.CreaturesBases.Remove(TargetCreatureBase);
                }
                foreach (Character character in CharactersWithin8)
                {
                    if (Math.Abs(character.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(character.MapY - TargetCreatureBase.MapY) <= 4)
                    {
                        if (TargetCreatureBase.HP < 1)
                            character.AddMapItem(CurrentMapItem);
                        else
                            character.UpdateCreatureBaseHp(TargetCreatureBase);
                    }
                }
            }

            if (ticksLeft > 0 && TargetCreatureBase.HP > 0)
            {
                ticksLeft--;
                spellTimer.Start();
            }
            else
                RemoveSpell(true, true);
        }

        public void InstantCast(CreatureBase castingCreature, CreatureBase targetCreatureBase, SpellIcon _spellIcon, int castLevel)
        {
            if (InitializeInstantCast(castingCreature, targetCreatureBase, _spellIcon, castLevel, true) == false)
                return;

            MainCast(castingCreature);
        }
    }
}
